
import { _decorator, Component, input, Input, EventKeyboard, KeyCode, RigidBody2D, CCFloat, Vec2, Node, Animation, Sprite, Color, CircleCollider2D, Contact2DType, Collider2D, IPhysics2DContact, Prefab, instantiate, find, AudioClip, AudioSource, animation } from 'cc';
import { Enemy } from './animy/Enemy';
import { Bullet } from './Bullet';
import { bulletList, ColliderTag, eventTarget } from './Globle';
import { Rocket } from './Rocket';
import { Thunder } from './Thunder';
const { ccclass, property } = _decorator;

@ccclass('Player')
export class Player extends Component {
    @property(CCFloat) speed: number;
    @property(CCFloat) fireBulletDelay: number;
    @property(CCFloat) bulletSpeed: number;
    @property(CCFloat) bulletDistance: number;
    @property(CCFloat) thunderSpeed: number;
    @property(CCFloat) thunderDistance: number;
    @property(Prefab) thunder: Prefab;
    @property(Prefab) rocket: Prefab;
    @property(Prefab) bullet: Prefab;
    @property(CCFloat) invincibleTime: number;
    @property(AudioClip) died_audio: AudioClip;
    @property(AudioClip) bullet_audio: AudioClip;
    @property(AudioClip) fire_tool_audio: AudioClip;
    private collider: CircleCollider2D;
    private rigidbody: RigidBody2D;
    private sprite: Node;
    private invincibleAnimation: Animation;
    private animator: animation.AnimationController;
    private audioSource: AudioSource;
    public isInvincible: boolean = true;
    private isDied: boolean = false;
    private gameScene: Node;
    private isFireBullet: boolean = false;
    private frimeTime: number = 0;
    private fire_lv = 0;
    public thunderList: Array<Node> = [];
    private current_direction: Vec2 = new Vec2(0, 1);
    private move_type = {
        up: false,
        left: false,
        right: false,
        down: false,

    }
    start() {
        this.gameScene = find('GameScene');
        this.rigidbody = this.getComponent(RigidBody2D);
        this.audioSource = this.getComponent(AudioSource);
        this.rigidbody.enabledContactListener = true;
        this.sprite = this.node.children.find(v => v.name == 'sprite')!;
        let sprite: Sprite = this.sprite.getComponent(Sprite);
        this.invincibleAnimation = this.getComponent(Animation)
        this.animator = this.sprite.getComponent(animation.AnimationController);
        this.invincibleAnimation.play();
        this.scheduleOnce(() => {
            this.isInvincible = false;
            this.invincibleAnimation.stop();
            sprite.color = new Color(255, 255, 255, 255);
        }, this.invincibleTime);
        this.collider = this.getComponent(CircleCollider2D);
        if (this.collider) {
            this.collider.on(Contact2DType.BEGIN_CONTACT, this.onContact, this);
            this.collider.on(Contact2DType.END_CONTACT, this.onContact, this);
        }
        input.on(Input.EventType.KEY_DOWN, this.keyDown, this);
        input.on(Input.EventType.KEY_UP, this.keyUp, this);
        eventTarget.on('thunderDestory', this.onThunderDestory, this);
    }

    private keyDown(e: EventKeyboard) {
        switch (e.keyCode) {
            case KeyCode.KEY_W: this.animator.setValue('up', true); this.move_type.up = true; break;
            case KeyCode.KEY_A: this.animator.setValue('left', true); this.move_type.left = true; break;
            case KeyCode.KEY_S: this.animator.setValue('down', true); this.move_type.down = true; break;
            case KeyCode.KEY_D: this.animator.setValue('right', true); this.move_type.right = true; break;
            case KeyCode.KEY_U: this.isFireBullet = true; break;
            case KeyCode.KEY_I: this.fire(); break;
        }
        if (this.isDied) return;
        let state = this.move_type.up || this.move_type.right || this.move_type.down || this.move_type.left;
        if (state) this.current_direction = this.setDirection();

    }
    private keyUp(e: EventKeyboard) {
        switch (e.keyCode) {
            case KeyCode.KEY_W: this.animator.setValue('up', false); this.move_type.up = false; break;
            case KeyCode.KEY_A: this.animator.setValue('left', false); this.move_type.left = false; break;
            case KeyCode.KEY_S: this.animator.setValue('down', false); this.move_type.down = false; break;
            case KeyCode.KEY_D: this.animator.setValue('right', false); this.move_type.right = false; break;
            case KeyCode.KEY_U: this.isFireBullet = false; break;
        }
        if (this.isDied) return;
        let state = this.move_type.up || this.move_type.right || this.move_type.down || this.move_type.left;
        if (state) this.current_direction = this.setDirection();
    }

    private onContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        switch (otherCollider.tag) {
            case ColliderTag.enemyBullet:
            case ColliderTag.enemy://敌人
                if (!this.isInvincible && !this.isDied) this.died();
                break;
            case ColliderTag.enemy_people:
                let obj = otherCollider.node.getComponent(Enemy);
                if (obj) obj.onContact(this.collider);
                break;
        }
    }

    //手雷或导弹销毁时
    private onThunderDestory(thunder: Node) {
        let index = this.thunderList.findIndex(v => v.uuid == thunder.uuid);
        if (~index) this.thunderList.splice(index, 1);
    }

    //开火
    private fire() {
        if (this.isDied || this.thunderList.length) return;
        if (this.fire_lv == 0) {
            //手雷
            let thunderNode = instantiate(this.thunder);
            this.thunderList.push(thunderNode);
            thunderNode.position = this.node.position;
            this.gameScene.addChild(thunderNode);
            thunderNode.getComponent(Thunder).setDirection(this.current_direction.clone(), this.thunderSpeed, ColliderTag.playerBullet, this.thunderDistance);
        }else{
            //火箭炮
            let rocketNode = instantiate(this.rocket);
            this.thunderList.push(rocketNode);
            rocketNode.position = this.node.position;
            this.gameScene.addChild(rocketNode);
            rocketNode.getComponent(Rocket).setDirection(this.current_direction.clone(), this.thunderSpeed*1.5, ColliderTag.playerBullet, this.thunderDistance,this.fire_lv);
        }

    }

    //机枪
    private fireBullet() {
        if (this.isDied) return;
        let bullet: Node;
        this.audioSource.clip = this.bullet_audio;
        this.audioSource.play();
        if (bulletList.length) {
            bullet = bulletList.find(v => v.active == false);
            if (!bullet) {
                bullet = instantiate(this.bullet);
                bulletList.push(bullet);
            }
        } else {
            bullet = instantiate(this.bullet);
            bulletList.push(bullet);
        }
        bullet.position = this.node.position;
        this.gameScene.addChild(bullet);
        bullet.active = true;
        bullet.getComponent(CircleCollider2D).tag = ColliderTag.playerBullet;
        let bulletScript = bullet.getComponent(Bullet);
        bulletScript.speed = this.bulletSpeed;
        bulletScript.setDirection(new Vec2(0, 1), 'player', this.bulletDistance);
    }

    //设置方向
    private setDirection() {
        let vec = new Vec2();
        if (this.move_type.up) vec.set(vec.x, vec.y + this.speed);
        if (this.move_type.down) vec.set(vec.x, vec.y - this.speed);
        if (this.move_type.left) vec.set(vec.x - this.speed, vec.y);
        if (this.move_type.right) vec.set(vec.x + this.speed, vec.y);
        return vec.normalize();
    }

    /**
     * 火力升级
     * fireLvUp
     * @param num 等级数
     */
    public fireLvUp(num: number) {
        this.audioSource.clip = this.fire_tool_audio;
        this.audioSource.play();
        this.fire_lv+=num;
    }


    update(deltaTime: number) {
        this.frimeTime += deltaTime;
        if (this.isDied) {
            this.rigidbody.linearVelocity = Vec2.ZERO;
            return;
        }
        let vec = new Vec2();
        if (this.move_type.up) vec.set(vec.x, vec.y + this.speed);
        if (this.move_type.down) vec.set(vec.x, vec.y - this.speed);
        if (this.move_type.left) vec.set(vec.x - this.speed, vec.y);
        if (this.move_type.right) vec.set(vec.x + this.speed, vec.y);
        this.rigidbody.linearVelocity = vec;
        if (this.isFireBullet && this.frimeTime >= this.fireBulletDelay) {
            this.fireBullet();
            this.frimeTime = 0;
        }
    }

    onDestroy() {
        input.off(Input.EventType.KEY_DOWN, this.keyDown, this);
        input.off(Input.EventType.KEY_UP, this.keyUp, this);
        if (this.collider) {
            this.collider.off(Contact2DType.BEGIN_CONTACT, this.onContact, this);
            this.collider.off(Contact2DType.END_CONTACT, this.onContact, this);
        }
    }

    /**
     * died
     */
    public died() {
        this.isDied = true;
        this.audioSource.clip = this.died_audio;
        this.audioSource.play();
        this.invincibleAnimation.play("bomb")

    }
    public onDied() {
        this.sprite.active = false;
        eventTarget.emit("playerDied", this.node.position);
        this.scheduleOnce(() => {
            this.node.destroy();
        }, 1);

    }
}
